home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
kcl
/
akcl
/
kcl.lha
/
c
/
earith.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-06-04
|
7KB
|
466 lines
/*
(c) Copyright Taiichi Yuasa and Masami Hagiya, 1984. All rights reserved.
Copying of this file is authorized to users who have executed the true and
proper "License Agreement for Kyoto Common LISP" with SIGLISP.
*/
/*
earith.c
EXTENDED_MUL and EXTENDED_DIV perform 32 bit multiplication and
division, respectively.
EXTENDED_MUL(D,Q,R,HP,LP)
calculates D*Q+R and saves the result into the locations HP and LP.
D, Q, and R are 32 bit non-negative integers and HP and LP are
word addresses. The word at LP will contain the lower 31 (not 32)
bits of the result and its most significant bit is set 0. The word
at HP will contain the rest of the result and its MSB is also set 0.
EXTENDED_DIV(D,H,L,QP,RP)
divides [H:L] by D and saves the quotient and the remainder into
the locations QP and RP, respectively. D, H, L are 32 bit non-negative
integers and QP and RP are word addresses. Here, [H:L] means the
64 bit integer (imaginary) represented by H and L as follows.
63 62 31 30 0
|0|0|<lower 31 bits of H>|<lower 31 bits of L>|
Although [H:L] is 64 bits, you can assume that the quotient is always
represented as 32 bit non-negative integer.
*/
#include "include.h"
#ifdef VAX
extended_mul(d, q, r, hp, lp)
int d, q, r;
int *hp, *lp;
{
asm(" emul 4(ap),8(ap),12(ap),r0");
asm(" ashq $1,r0,r0");
asm(" rotl $-1,r0,r0");
asm(" movl r0,*20(ap)");
asm(" movl r1,*16(ap)");
}
extended_div(d, h, l, qp, rp)
int d, h, l;
int *qp, *rp;
{
asm(" clrl r0");
asm(" movl 8(ap),r1");
asm(" ashq $-1,r0,r0");
asm(" addl2 12(ap),r0");
asm(" ediv 4(ap),r0,*16(ap),*20(ap)");
}
#endif
#ifdef MC68K
extended_mul(d, q, r, hp, lp)
int d, q, r;
int *hp, *lp;
{
asm(" movl d2,a7@-");
asm(" movw a6@(8),d0");
asm(" mulu a6@(14),d0");
asm(" movw a6@(10),d1");
asm(" mulu a6@(12),d1");
asm(" addl d1,d0");
asm(" movw a6@(8),d1");
asm(" mulu a6@(12),d1");
asm(" movw a6@(10),d2");
asm(" mulu a6@(14),d2");
asm(" swap d2");
asm(" addw d0,d2");
asm(" swap d2");
asm(" swap d0");
asm(" addxw d0,d1");
asm(" clrl d0");
asm(" swap d1");
asm(" addxw d0,d1");
asm(" swap d1");
asm(" addl a6@(16),d2");
asm(" addxl d0,d1");
asm(" lsll #1,d2");
asm(" roxll #1,d1");
asm(" lsrl #1,d2");
asm(" movl a6@(20),a0");
asm(" movl d1,a0@");
asm(" movl a6@(24),a0");
asm(" movl d2,a0@");
asm(" movl a7@+,d2");
}
extended_div(d, h, l, qp, rp)
int d, h, l;
int *qp, *rp;
{
asm(" moveml #0x3000,a7@-");
asm(" moveml a6@(8),#0x307");
asm(" lsll #1,d2");
asm(" addql #1,d2");
asm(" movw #31,d3");
asm("label2: subl d0,d1");
asm(" bccs label1");
asm(" addl d0,d1");
asm("label1: roxll #1,d2");
asm(" roxll #1,d1");
asm(" dbf d3,label2");
asm(" roxrl #1,d1");
asm(" notl d2");
asm(" movl d2,a0@");
asm(" movl d1,a1@");
asm(" moveml a7@+,#0xc");
}
#endif
#ifndef NEWS
#ifdef MC68020
extended_mul(d, q, r, hp, lp)
int d, q, r;
int *hp, *lp;
{
asm(" movl d2,a7@-");
asm(" clrl d2");
asm(" movl a6@(8),d0");
asm(" mulul a6@(12),d1:d0");
asm(" addl a6@(16),d0");
asm(" addxl d2,d1");
asm(" lsll #1,d0");
asm(" roxll #1,d1");
asm(" lsrl #1,d0");
asm(" movl a6@(20),a0");
asm(" movl d1,a0@");
asm(" movl a6@(24),a0");
asm(" movl d0,a0@");
}
extended_div(d, h, l, qp, rp)
int d, h, l;
int *qp, *rp;
{
asm("moveml a6@(12),#0x303");
asm("lsll #1,d1");
asm("lsrl #1,d0");
asm("roxrl #1,d1");
asm("divul a6@(8),d0:d1");
asm("movl d0,a1@");
asm("movl d1,a0@");
}
#endif
#endif
#ifdef ATT3B2
extended_mul(d, q, r, hp, lp)
int d, q, r;
int *hp, *lp;
{
register int *r8, *r7, *r6, *r5, *r4;
asm(" movh 0(%ap),%r5"); /* R5 <= high(d) */
asm(" andw3 &0xffff,0(%ap),%r6"); /* R6 <= low(d) */
asm(" movh 4(%ap),%r7"); /* R7 <= high(q) */
asm(" andw3 &0xffff,4(%ap),%r8"); /* R8 <= low(q) */
asm(" mulw3 %r6,%r8,%r0"); /* R0 <= low(d)*low(q) */
asm(" andw3 &0x80000000,%r0,%r1"); /* save MSB(R0) */
asm(" lrsw3 &16,%r1,%r1");
asm(" andw2 &0x7fffffff,%r0"); /* MSB(R0) <= 0 */
asm(" addw2 8(%ap),%r0"); /* R0 <= R0 + r */
asm(" andw3 &0xffff,%r0,%r4"); /* save low(R0) */
asm(" lrsw3 &16,%r0,%r0"); /* R0 >> 16 */
asm(" addw2 %r1,%r0"); /* resume MSB(R0) */
asm(" mulw3 %r5,%r8,%r2"); /* R0 <= high(d)*low(q) */
asm(" addw2 %r2,%r0"); /* + R0 */
asm(" andw3 &0x80000000,%r0,%r1"); /* save MSB(R0) */
asm(" lrsw3 &15,%r1,%r1");
asm(" andw2 &0x7fffffff,%r0"); /* MSB(R0) <= 0 */
asm(" mulw3 %r7,%r6,%r2"); /* R0 <= low(d)*high(q) */
asm(" addw2 %r2,%r0"); /* + R0 */
asm(" andw3 &0x7fff,%r0,%r2"); /* R2 <= low(R0) */
asm(" llsw2 &16,%r2"); /* high <= low(R2)*2^16 */
asm(" orw3 %r2,%r4,*16(%ap)"); /* + low(R4) */
asm(" lrsw3 &15,%r0,%r0"); /* R0 >> 15, not 16 */
asm(" addw2 %r1,%r0"); /* resume MSB(R0) */
asm(" mulw3 %r5,%r7,%r1"); /* high <= high(d)*high(q) */
asm(" llsw2 &1,%r1"); /* + R0 */
asm(" addw3 %r0,%r1,*12(%ap)");
}
extended_div(d, h, l, qp, rp)
int d, h, l;
int *qp, *rp;
{
register int *r8, *r7, *r6;
asm(" movw 0(%ap),%r2");
asm(" movw 4(%ap),%r0");
asm(" movw 8(%ap),%r1");
asm(" movw &0,%r8"); /* quotient to go */
asm(" movw &31,%r7"); /* loop counter */
asm("a: llsw2 &1,%r8"); /* R8 << 1, no need 1st time */
asm(" llsw2 &1,%r0"); /* R0 << 1 */
asm(" llsw2 &1,%r1"); /* R1 << 1 */
asm(" jge b"); /* skip if MSB(R1) = 0 */
asm(" orw2 &1,%r0"); /* LSB(R0) <= 1 */
asm("b: subw3 %r2,%r0,%r6"); /* R6 <= R0 - R2 */
asm(" jl c"); /* skip if R5 < 0 */
asm(" movw %r6,%r0"); /* R0 <= R0 - R2 */
asm(" orw2 &1,%r8"); /* LSB(R8) <= 1 */
asm("c: subw2 &1,%r7"); /* R7 <= R7 - 1 */
asm(" jg a"); /* repeat while R3 > 0 */
asm(" movw %r8,*12(%ap)");
asm(" movw %r0,*16(%ap)");
}
#endif
#ifdef NS32K
#endif
#ifdef S3000
extended_mul(d, q, r, hp, lp)
int d, q, r;
int *hp, *lp;
{
long long int ld, lq, lr, z;
int zh, zl;
ld = d;
lq = q;
lr = r;
z = ld*lq+lr;
zl = (z & 0x000000007fffffffLL);
zh = (z >> 31LL);
*hp = zh;
*lp = zl;
}
extended_div(d, h, l, qp, rp)
int d, h, l;
int *qp, *rp;
{
long long int lh, ld, ll;
ld = d;
lh = h;
ll = l;
lh = (lh << 31LL);
lh = (lh | ll);
*qp = (lh/ld);
*rp = (lh%ld);
}
#endif
#ifdef IBMRT
#endif
#ifdef NEWS
extended_mul(d, q, r, hp, lp)
int d, q, r;
int *hp, *lp;
{
asm(" move.l d2,-(sp)");
asm(" clr.l d2");
asm(" move.l (8,fp),d0");
asm(" mulu.l (12,fp),d1:d0");
asm(" add.l (16,fp),d0");
asm(" addx.l d2,d1");
asm(" lsl.l #1,d0");
asm(" roxl.l #1,d1");
asm(" lsr.l #1,d0");
asm(" move.l (20,fp),a0");
asm(" move.l d1,(a0)");
asm(" move.l (24,a6),a0");
asm(" move.l d0,(a0)");
}
extended_div(d, h, l, qp, rp)
int d, h, l;
int *qp, *rp;
{
asm("movem.l (12,fp),#0x303");
asm("lsl.l #1,d1");
asm("lsr.l #1,d0");
asm("roxr.l #1,d1");
asm("divu.l (8,fp),d0:d1");
asm("move.l d0,(a1)");
asm("move.l d1,(a0)");
}
#endif